/* 
 * File:   ShapeList.cpp
 * Author: brady
 * 
 * Created on June 27, 2011, 7:39 PM
 */

#include <acceleration/ShapeList.h>

ShapeList::ShapeList() {
    boundingBox = BoundingBox::inverseBox();
}

ShapeList::ShapeList(const ShapeList& orig) {
}

ShapeList::~ShapeList() {
    for(int i = 0; i<shapes.size(); i++){
        if(shapes[i] != NULL) delete shapes[i];
    }
}

void ShapeList::addShape(Shape* shape){
    boundingBox = boundingBox.encompass(shape->getBoundingBox());
    shapes.push_back(shape);
}

void ShapeList::finalize(){
    return;
}

IntersectionResult ShapeList::getFirstIntersection(IntersectionParams& ip){
    vector<IntersectionResult> results = this->getAllIntersections(ip);
    //try manually searching for the correct entry
    //sort(results.begin(), results.end(), IntersectionResult::compare);
    IntersectionResult first;
    first.tVal = DBL_MAX;
    first.shape = NULL;
    for (int i=0; i<results.size(); i++){
        if(results[i].tVal < first.tVal){
            first = results[i];
        }
    }
    return first;
}

vector<IntersectionResult> ShapeList::getAllIntersections(IntersectionParams& ip){
    vector<IntersectionResult> results;
    IntersectionResult currentResult;
    for (int i = 0; i<shapes.size(); i++){
        currentResult.tVal = DBL_MAX;
        currentResult.shape = NULL;
        if(!shapes[i]->getBoundingBox().testIntersect(ip, NULL, NULL)){
            continue;
        }       
        bool hit = shapes[i]->testIntersect(ip, currentResult);
        if(hit){
            results.push_back(currentResult);
            //once we want to keep the reference, create a new instance
        }
    }
    return results;
}

IntersectionResult ShapeList::getAnyIntersection(IntersectionParams& ip){
    for (int i = 0; i<shapes.size(); i++){
        IntersectionResult cur;
        bool hit = shapes[i]->testIntersect(ip, cur);
        if(hit && cur.tVal < ip.getTMax() && cur.tVal > ip.getTMin()){
            return cur;
        }
    }
    IntersectionResult noHit;
    noHit.shape = NULL;
    noHit.tVal = DBL_MAX;
    return noHit;
}